package interview_09_01

import (
	"errors"
	"fmt"
	"sync"
)

type CQueue struct {
	stackIn  MyStack
	stackOut MyStack
}

func Constructor() CQueue {
	return CQueue{}
}

func (q *CQueue) AppendTail(value int) {
	for true {
		el, err := q.stackOut.Pop()
		if err != nil {
			break
		}
		q.stackIn.Push(el)
	}
	q.stackIn.Push(value)
	for true {
		el, err := q.stackIn.Pop()
		if err != nil {
			break
		}
		q.stackOut.Push(el)
	}
}

func (q *CQueue) DeleteHead() int {
	el, err := q.stackOut.Pop()
	if err != nil {
		return -1
	}
	return el
}

/**
 * Your CQueue object will be instantiated and called as such:
 * obj := Constructor();
 * obj.AppendTail(value);
 * param_2 := obj.DeleteHead();
 */

type MyStack struct {
	items []int
	l     sync.Mutex
}

func (m *MyStack) Push(n int) {
	m.l.Lock()
	defer m.l.Unlock()
	m.items = append(m.items, n)
}

func (m *MyStack) Pop() (int, error) {
	m.l.Lock()
	defer m.l.Unlock()
	if len(m.items) == 0 {
		return 0, errors.New("empty of stack")
	}
	el := m.items[len(m.items)-1]
	m.items = m.items[:len(m.items)-1]
	return el, nil
}

func (m *MyStack) Top() (int, error) {
	m.l.Lock()
	defer m.l.Unlock()
	if len(m.items) == 0 {
		return 0, errors.New("empty of stack")
	}
	el := m.items[len(m.items)-1]
	return el, nil
}

func (m *MyStack) Size() int {
	return len(m.items)
}

func (m *MyStack) Empty() bool {
	if len(m.items) == 0 {
		return true
	}
	return false
}

func (m MyStack) Show() {
	fmt.Println(m.items)
}

func operationQueue1() bool {

	obj := Constructor()
	fmt.Println(obj.DeleteHead())
	obj.AppendTail(5)
	obj.AppendTail(2)
	fmt.Println(obj.DeleteHead())
	fmt.Println(obj.DeleteHead())

	return true
}
